#pragma once
#include "abstract.hpp"
#include "detail.hpp"
#include<vector>

//消息类型
namespace rpc
{
    class JsonMessage : public BaseMessage
    {
    public:
        using ptr = std::shared_ptr<JsonMessage>;
        // 实现序列化+反序列化+校验函数
        // 序列化+反序列化+校验
        // 将json类型的数据序列化为string类型
        virtual std::string serilize() override
        {
            std::string body;
            bool ret = JSON::Serialization(_body, body);
            if (ret == false)
            {
                return std::string();
            }

            return body;
        }
        // 反序列化
        virtual bool unserilize(const std::string &msg) override
        {
            delog("msg:");
            std::cout << msg << std::endl;
            return JSON::UnSerialization(msg, _body);
        }

        // 校验不能由JsonMessage来写，因为不同的类型校验方式不一样
    protected:
        Json::Value _body;
    };

    // requstMessage
    class RequestMessage : public JsonMessage
    {
    public:
        using ptr = std::shared_ptr<RequestMessage>;
    };

    // ResponseMessage：大部分响应都只有响应状态码，校验响应状态码即可
    class ResponseMessage : public JsonMessage
    {
    public:
        using ptr = std::shared_ptr<ResponseMessage>;
        // 检查响应中是否由响应状态码
        virtual bool check() override
        {
            // 检查是否有响应码
            if (_body[KEY_RECODE].isNull() == true)
            {
                errlog("缺少响应码");
                return false;
            }
            // 检查响应码类型是否正确：是整型
            if (_body[KEY_RECODE].isIntegral() == false)
            {
                errlog("响应码类型错误");
                return false;
            }
            return true;
        }

        virtual void setRecode(const MY_CODE &recode)
        {
            _body[KEY_RECODE] = (int)recode;
        }

        virtual MY_CODE getRecode()
        {
            return (MY_CODE)_body[KEY_RECODE].asInt();
        }
    };

    // rpcRequst
    class RpcRequest : public RequestMessage
    {
    public:
        using ptr = std::shared_ptr<RpcRequest>;
        virtual bool check() override
        {
            // 检查请求方法
            if (_body[KEY_METHOD].isNull() == true || _body[KEY_METHOD].isString() == false)
            {
                errlog("rpc请求缺少方法或者方法类型错误");
                return false;
            }
            // 检查请求的参数
            if (_body[KEY_PARAMS].isNull() == true || _body[KEY_PARAMS].isObject() == false)
            {
                errlog("rpc请求缺少参数或者参数类型错误");
                return false;
            }
            return true;
        }

        // 获取方法+设置方法+获取参数+设置参数
        std::string getMethod()
        {
            return _body[KEY_METHOD].asString();
        }
        void setMethod(const std::string &method_name)
        {
            _body[KEY_METHOD] = method_name;
        }
        Json::Value getParams()
        {
            return _body[KEY_PARAMS];
        }
        void setParams(const Json::Value &params)
        {
            _body[KEY_PARAMS] = params;
        }
    };

    // topicRequest

    class TopicRequest : public RequestMessage
    {
    public:
        using ptr = std::shared_ptr<TopicRequest>;
        // 实现topic请求校验
        virtual bool check() override
        {
            // 主题类型是否为空或者是否为string类型？
            if (_body[KEY_TOPIC].isNull() || !_body[KEY_TOPIC].isString())
            {
                errlog("主题为空或者类型错误");
                return false;
            }
            // 操作类型是否正确？
            if (_body[KEY_OPTION_TYPE].isNull() || _body[KEY_OPTION_TYPE].isIntegral() == false)
            {
                errlog("操作类型错误");
                return false;
            }
            // 当主题类型是发布类型时检查消息内容是否正确？
            if (_body[KEY_OPTION_TYPE].asInt() == (int)TOPIC_OPTION::TOPIC_PUBLISH && (_body[KEY_TOPIC_MSG].isNull() ||
                                                                                       _body[KEY_TOPIC_MSG].isString() == false))
            {
                errlog("topic内容错误");
                return false;
            }

            return true;
        }

        // 主题名称的设置
        std::string getKeyTopic()
        {
            return _body[KEY_TOPIC].asString();
        }
        void setKeyTopic(const std::string &key)
        {
            _body[KEY_TOPIC] = key;
        }

        // 获取和设置topic操作类型
        TOPIC_OPTION getTopicOption()
        {
            return (TOPIC_OPTION)_body[KEY_OPTION_TYPE].asInt();
        }

        void setTopicOption(const TOPIC_OPTION &option)
        {
            _body[KEY_OPTION_TYPE] = (int)option;
        }

        // 获取和设置请求内容
        std::string getTopicMessage()
        {
            return _body[KEY_TOPIC_MSG].asString();
        }
        void setTopicMessage(const std::string &msg)
        {
            _body[KEY_TOPIC_MSG] = msg;
        }
    };

    // 服务端主要要校验和设置主机，操作类型，方法
    using Address = std::pair<std::string, int>;
    class ServerRequest : public RequestMessage
    {
    public:
        using ptr = std::shared_ptr<ServerRequest>;
        virtual bool check() override
        {
            // 主题类型是否为空或者是否为string类型？
            if (_body[KEY_METHOD].isNull() || !_body[KEY_METHOD].isString())
            {
                errlog("方法为空或者类型错误");
                return false;
            }
            // 操作类型是否正确？
            if (_body[KEY_OPTION_TYPE].isNull() || _body[KEY_OPTION_TYPE].isIntegral() == false)
            {
                errlog("操作类型错误");
                return false;
            }
            // 校验主机是否正确：主要校验ip和port
            if (_body[HOST].isNull() ||
                _body[HOST][HOST_IP].isNull() ||
                _body[HOST][HOST_IP].isString() == false ||
                _body[HOST][HOST_PORT].isNull() ||
                _body[HOST][HOST_PORT].isInt() == false)
            {
                errlog("主机错误");
                return false;
            }

            return true;
        }

        // 获取和设置方法名称
        std::string getMethod()
        {
            return _body[KEY_METHOD].asString();
        }
        void setMethod(const std::string &method_name)
        {
            _body[KEY_METHOD] = method_name;
        }

        // 获取和设置topic操作类型
        int getOption()
        {
            return _body[KEY_OPTION_TYPE].asInt();
        }

        void setOptionType(const rpc::SERVICE_TYPE&type)
        {
            _body[KEY_OPTION_TYPE] = (int)type;
        }

        // 获取和设置host
        Address getHost()
        {
            Address address;
            address.first = _body[HOST][HOST_IP].asString();
            address.second =_body[HOST][HOST_PORT].asInt();
            return  address;
        }

        void setHost(const Address &host)
        {
            // 先将host转化为json::val
            Json::Value val;
            val[HOST_IP] = host.first;
            val[HOST_PORT] = host.second;
            // 再将val赋值给_body
            _body[HOST] = val;
        }

        // void setMytype(const SERVICE_TYPE &type)
        // {
        //     _body[KEY_OPTION_TYPE] = (int)type;
        // }

    
    };

    // rpcResponse实现
    class RpcResponse:public ResponseMessage
    {
    public:
        using ptr = std::shared_ptr<RpcResponse>;
        // 检查响应类型错误和结果
        virtual bool check() override
        {
            if (_body[KEY_RECODE].isNull() || _body[KEY_RECODE].isInt() == false)
            {
                errlog("响应状态码为空或者类型错误");
                return false;
            }
            return true;
        }

        // 响应状态码设置和获取+结果的响应和转换
        std::string getMethod()
        {
            return _body[KEY_METHOD].asString();
        }
        void setMethod(const std::string &method_name)
        {
            _body[KEY_METHOD] = method_name;
        }
        Json::Value getParams()
        {
            return _body[KEY_PARAMS];
        }
        void setParams(const Json::Value &params)
        {
            _body[KEY_PARAMS] = params;
        }
        // 获取和设置结果
        Json::Value& getResult()
        {
            return _body[kEY_RESULT];
        }

        void setResult(const Json::Value &val)
        {
            _body[kEY_RESULT] = val;
        }

        int getOptionType()
        {
            return _body[KEY_OPTION_TYPE].asInt();
        }
    };

    class TopicResponse: public ResponseMessage
    {
    public:
        using ptr = std::shared_ptr<TopicResponse>;
        // 不需要重写校验
        // 添加设置和获取校验码接口
    };

    // 主机+响应状态码+方法
    // 响应状态码：上线+下线+服务响应状态码：服务发现中没有请求信息
    class ServerResponse: public ResponseMessage
    {
    public:
        using ptr = std::shared_ptr<ServerResponse>;
        // 重写校验方法
        virtual bool check() override
        {
            //判断方法是否正确？
            if(_body[KEY_METHOD].isNull()||_body[KEY_METHOD].isString() == false)
            {
                errlog("响应方法错误");
                return false;
            }

            //响应要有类型,判断类型
            if(_body[KEY_RECODE].isNull()||_body[KEY_RECODE].isInt() == false)
            {
                errlog("响应类型错误");
                return false;
            }

            //当响应类型时发现时不需要判断host主机
            if (_body[KEY_OPTION_TYPE].asInt()!= (int)(SERVICE_TYPE::SERVICE_DISCOVERY)&&
                (_body[HOST].isArray()==false||
                _body[HOST].isNull()||
                _body[KEY_METHOD].isString() == false||
                _body[KEY_METHOD].isNull()
                )
                )
             {
                 errlog("服务中响应信息字段错误");
                 return false;
             }

             return true;
        }
        // 获取和设置方法名称
        void setMethod(const std::string &method_name)
        {
            _body[KEY_METHOD] = method_name;
        }
        std::string getMethod()
        {
            return _body[KEY_METHOD].asString();
        }
        // 获取主机序列和设置主机序列信息
        void setHosts(const std::vector<Address> &addrs)
        {
            for (auto e : addrs)
            {
                Json::Value val;
                val[HOST_IP] = e.first;
                val[HOST_PORT] = e.second;
                _body[HOST].append(val);
            }
        }
        std::vector<Address> getHosts()
        {
            std::vector<Address> hosts;
            int sz = _body[HOST].size();
            for (int i = 0; i < sz;i++)
            {
                Address val;
                val.first = _body[HOST][i][HOST_IP].asString();
                val.second = _body[HOST][i][HOST_PORT].asInt();
                hosts.push_back(val);
            }
            return hosts;
        }

        void setOptype(SERVICE_TYPE optype)
        {
            _body[KEY_OPTION_TYPE] = (int)optype;
        }
    };

    //实现消息对象的生产工厂
    class MessageFactory
    {
        public:
        static BaseMessage::ptr create(MY_TYPE mytype)
        {
             switch (mytype)
             {
             case MY_TYPE::REQ_RPC:return std::make_shared<RpcRequest>();
             case MY_TYPE::RSP_RPC:return std::make_shared<RpcResponse>();
             case MY_TYPE::REQ_TOPIC:return std::make_shared<TopicRequest>();
             case MY_TYPE::RSP_TOPIC:return std::make_shared<TopicResponse>();
             case MY_TYPE::REQ_SERVICE:return std::make_shared<ServerRequest>();
             case MY_TYPE::RSP_SERVICE:return std::make_shared<ServerResponse>();
            
             }

             //类型不对就返回空
             return BaseMessage::ptr();
        }

        //来个通用类型
        template<typename T,typename ...Args>
        static std::shared_ptr<T> create(Args&&...args)
        {
            return std::make_shared<T>(std::forward<Args>(args)...);
        }
    };
}